<?php
/**
 * 验证码类
 * @author: langming
 * @date: 2021/8/24 下午6:33
 */

namespace Langming\Captcha;

use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Redis;

class Captcha
{
    //配置
    public $config = null;

    //默认存储配置
    public $cacheDefault = [
        'driver' => 'session',
        'redis' => [
            'connection' => 'default'
        ],
        'prefix' => 'captcha:', //缓存前缀
        'expire' => 180 //有效期
    ];

    public function __construct($config)
    {
        $this->config = $config;
    }

    /**
     * 生成验证码并写入缓存
     * @param null $config
     * @throws \ImagickException
     */
    public function create($config = null)
    {
        //生成
        $config = $config ? array_replace($this->config, $config) : $this->config;
        $Captcha = (new CaptchaService)->create($config);
        if ($config['returnType'] && strtolower($config['returnType']) == 'base64') {
            $capData = [
                'img' => $Captcha->getImageBase64()
            ];
        }else{
            $capData = [
                'img' => $Captcha->getImageByte()
            ];
        }

        $cacheData = [
            'code' => $Captcha->getImageCode(),
            'time' => time()
        ];
        $config = $Captcha->getConfigs()['cache'] ?? $this->cacheDefault;
        $driver = $config['driver'] ?? 'session';
        $prefix = $config['prefix'] ?? '';
        $expire = $config['expire'] ?? 120;

        //根据驱动写入
        switch ($driver) {
            case 'redis':
                $codeKey = $prefix . $this->uuid(); //生成key
                $connection = $config['redis']['connection'] ?? 'default';
                $capData['codeKey'] = $codeKey;
                $cacheData = json_encode($cacheData);
                Redis::connection($connection)->setex($codeKey, $expire, $cacheData);
                break;
            case 'session':
                Session::put($prefix, $cacheData);
                Session::save();
                break;
        }
        unset($Captcha);
        return $capData;
    }

    /**
     * 验证是否正确和有效
     * @param $code
     * @param null $key
     * @return int|void
     * @throws \Laravel\Octane\Exceptions\DdException
     */
    public function verify($code, $key = null)
    {
        //获得配置
        $config = $this->config['cache'] ?: $this->cacheDefault;
        $driver = $config['driver'] ?? 'session';
        $prefix = $config['prefix'] ?? '';
        $expire = $config['expire'] ?? 120;
        if ($driver == 'session') {
            $cacheCode = Session::get($prefix);
            Session::forget($prefix); //验证一次立即清除
            if (!$cacheCode) return 0; //不存在
            if ((time() - $cacheCode['time']) > $expire) return 0; //已过期
            if ($cacheCode['code'] == $code) return 1; //正确，验证通过
            return -1; //验证码不正确
        }
        if ($driver == 'redis') {
            if (!$key) return 0;
            $cacheCode = Redis::get($key);
            $cacheCode = json_decode($cacheCode, true);
            Redis::del($key); //验证一次立即清除
            if (!$cacheCode) return 0;
            if ($cacheCode['code'] == $code) return 1;
            return -1;
        }
    }

    /**
     * 生成uuid
     * @return string
     */
    public function uuid()
    {
        if (function_exists('com_create_guid')) {
            return trim(com_create_guid(), '{}');
        } else {
            mt_srand((float)microtime() * 10000); //optional for php 4.2.0 and up.
            $charid = strtoupper(md5(uniqid(rand(), true)));
            $hyphen = chr(45); // "-"
            $uuid = substr($charid, 0, 8) . $hyphen
                . substr($charid, 8, 4) . $hyphen
                . substr($charid, 12, 4) . $hyphen
                . substr($charid, 16, 4) . $hyphen
                . substr($charid, 20, 12);
            return $uuid;
        }
    }
}
